﻿using System.Collections.Generic;

namespace Framework.Task
{
    /// <summary>
    /// 任务池
    /// </summary>
    /// <typeparam name="T">任务类型</typeparam>
    public class TaskPool<T> where T : ITask
    {
        private Stack<ITaskAgent<T>> m_FreeTaskAgent = null;
        private LinkedList<ITaskAgent<T>> m_WorkingTaskAgent = null;
        private LinkedList<T> m_WaitingTask = null;

        /// <summary>
        /// 构造函数
        /// </summary>
        public TaskPool()
        {
            m_FreeTaskAgent = new Stack<ITaskAgent<T>>();
            m_WorkingTaskAgent = new LinkedList<ITaskAgent<T>>();
            m_WaitingTask = new LinkedList<T>();
        }
        /// <summary>
        /// 空闲的任务代理器数量
        /// </summary>
        public int FreeTaskAgentCount
        {
            get
            {
                return m_FreeTaskAgent.Count;
            }
        }
        /// <summary>
        /// 工作中的任务代理器数量
        /// </summary>
        public int WorkingTaskAgentCount
        {
            get
            {
                return m_WorkingTaskAgent.Count;
            }
        }
        /// <summary>
        /// 所有任务代理器数量
        /// </summary>
        public int TotalTaskAgentCount
        {
            get
            {
                return m_WorkingTaskAgent.Count + m_FreeTaskAgent.Count;
            }
        }
        /// <summary>
        /// 等待现在的任务数量
        /// </summary>
        public int WaitingTaskCount
        {
            get
            {
                return m_WaitingTask.Count;
            }
        }
        /// <summary>
        /// 添加任务代理器
        /// </summary>
        /// <param name="agent">要添加的任务代理器</param>
        public void AddTaskAgent(ITaskAgent<T> agent)
        {
            if (agent == null || m_FreeTaskAgent.Contains(agent)) return;
            agent.Init();
            m_FreeTaskAgent.Push(agent);
        }
        /// <summary>
        /// 添加任务
        /// </summary>
        /// <param name="task">要添加的任务/param>
        public void AddTask(T task)
        {
            if (task == null) return;
            m_WaitingTask.AddLast(task);
        }
        /// <summary>
        /// 移出指定id的任务
        /// </summary>
        /// <param name="taskId">任务id</param>
        public void RemoveTask(int taskId)
        {
            LinkedListNode<T> currentTask = m_WaitingTask.First;
            while(currentTask != null)
            {
                if(currentTask.Value.TaskId == taskId)
                {
                    m_WaitingTask.Remove(currentTask);
                    break;
                }
                currentTask = currentTask.Next;
            }
            LinkedListNode<ITaskAgent<T>> currentAgent = m_WorkingTaskAgent.First;
            while(currentAgent != null)
            {
                if(currentAgent.Value.Task.TaskId == taskId)
                {
                    m_WorkingTaskAgent.Remove(currentAgent);
                    currentAgent.Value.Reset();
                    m_FreeTaskAgent.Push(currentAgent.Value);
                    break;
                }
                currentAgent = currentAgent.Next;
            }
        }
        /// <summary>
        /// 移出所有的任务
        /// </summary>
        public void RemoveAllTask()
        {
            m_WaitingTask.Clear();
            LinkedListNode<ITaskAgent<T>> currentAgent = m_WorkingTaskAgent.First;
            while(currentAgent != null)
            {
                currentAgent.Value.Reset();
                m_FreeTaskAgent.Push(currentAgent.Value);
                currentAgent = currentAgent.Next;
            }
            m_WorkingTaskAgent.Clear();
        }
        /// <summary>
        /// 销毁
        /// </summary>
        public void Destroy()
        {
            while(m_FreeTaskAgent.Count > 0)
            {
                m_FreeTaskAgent.Pop().Destroy();
            }
            LinkedListNode<ITaskAgent<T>> currentAgent = m_WorkingTaskAgent.First;
            while(currentAgent != null)
            {
                currentAgent.Value.Destroy();
                currentAgent = currentAgent.Next;
            }
            m_WorkingTaskAgent.Clear();
            m_WaitingTask.Clear();
        }
        /// <summary>
        /// 轮询接口
        /// </summary>
        /// <param name="frameTime">逻辑一帧时间</param>
        /// <param name="realTime">实际一帧时间</param>
        public void Update(float frameTime, float realTime)
        {
            LinkedListNode<ITaskAgent<T>> currentWorkAgentNode = m_WorkingTaskAgent.First;
            while(currentWorkAgentNode != null)
            {
                if(currentWorkAgentNode.Value.Task.Done)
                {
                    LinkedListNode<ITaskAgent<T>> next = currentWorkAgentNode.Next;
                    m_WorkingTaskAgent.Remove(currentWorkAgentNode);
                    currentWorkAgentNode.Value.Reset();
                    m_FreeTaskAgent.Push(currentWorkAgentNode.Value);
                    currentWorkAgentNode = next;
                    continue;
                }
                currentWorkAgentNode.Value.Update(frameTime, realTime);
                currentWorkAgentNode = currentWorkAgentNode.Next;
            }
            while(m_FreeTaskAgent.Count > 0 && m_WaitingTask.Count > 0)
            {
                ITaskAgent<T> agent = m_FreeTaskAgent.Pop();
                T task = m_WaitingTask.First.Value;
                m_WaitingTask.RemoveFirst();
                m_WorkingTaskAgent.AddLast(agent);
                agent.Start(task);
                if(agent.Task.Done)
                {
                    agent.Reset();
                    m_WorkingTaskAgent.Remove(agent);
                    m_FreeTaskAgent.Push(agent);
                }
            }
        }
    }
}
